package handler

import (
	"context"
	"fmt"
	"github.com/jinzhu/gorm"
	"rpcSrv/dbs/mysqlGORM"
	"rpcSrv/entitys"
	pb "rpcSrv/proto/comment"
	"rpcSrv/utils"
	"time"
)

type CommentHdl struct {
}

func (this *CommentHdl) CreateComment(ctx context.Context, req *pb.CreateReqParams) (resp *pb.Comment, err error) {
	is_reply := req.GetIsReply()
	reply_id := req.GetReplyId()
	target_id := req.GetTargetId()
	from_uid := req.GetFromUid()
	to_uid := req.GetToUid()
	tb_name := req.GetTbName()
	content := req.GetContent()
	if from_uid == 0 {
		return nil, fmt.Errorf("用户ID不可为空")
	}
	if target_id == 0 {
		return nil, fmt.Errorf("评论目标ID不可为空")
	}
	if content == "" {
		return nil, fmt.Errorf("评论内容不可为空")
	}
	if tb_name == "" {
		return nil, fmt.Errorf("评论目标表名称不可为空")
	}
	if is_reply == 1 {
		if reply_id == 0 {
			return nil, fmt.Errorf("回复评论ID不可为空")
		}
		if to_uid == 0 {
			return nil, fmt.Errorf("回复用户ID不可为空")
		}
	}
	db, err := mysqlGORM.GetMysqlDB()
	if utils.CheckErr(err) {
		return nil, err
	}
	tx := db.Begin()
	cmt := new(entitys.Comment)
	cmt.IsReply = int(is_reply)
	cmt.ReplyId = int(reply_id)
	cmt.TargetId = int(target_id)
	cmt.FromUid = int(from_uid)
	cmt.ToUid = int(to_uid)
	cmt.TbName = tb_name
	cmt.Content = content
	cmt.Status = 1
	cmt.CreatedTimestamp = time.Now().Unix()
	cmt.UpdatedTimestamp = time.Now().Unix()
	if err = tx.Table(cmt.TableName()).Create(cmt).Error; utils.CheckErr(err) {
		tx.Rollback()
		return nil, err
	}
	if err = tx.Table(tb_name).Where("id = ?", target_id).UpdateColumn("comment_number", gorm.Expr("comment_number + ?", 1)).Error; utils.CheckErr(err) {
		tx.Rollback()
		return nil, err
	}
	if is_reply == 1 {
		if err = tx.Table(cmt.TableName()).Where("id = ?", reply_id).UpdateColumn("reply_number", gorm.Expr("reply_number + ?", 1)).Error; utils.CheckErr(err) {
			tx.Rollback()
			return nil, err
		}
	}
	tx.Commit()
	resp = new(pb.Comment)
	db.Table(fmt.Sprintf("%v as a", new(entitys.Comment).TableName())).
		Joins(fmt.Sprintf("inner join %v as b on a.from_uid=b.id", new(entitys.User).TableName())).
		Select("a.id,a.reply_number,a.like_number,a.target_id,a.is_reply,a.from_uid,a.content,a.created_timestamp,b.head_image as from_head_image,b.nickname as from_nickname").
		Where("a.id = ?", cmt.ID).
		Limit(1).Scan(resp)
	return resp, nil
}

func (this *CommentHdl) GetComments(ctx context.Context, req *pb.GetCommentReqParams) (resp *pb.CommentList, err error) {
	target_id := req.GetTargetId()
	tb_name := req.GetTbName()
	if target_id == 0 {
		return nil, fmt.Errorf("评论目标ID不可为空")
	}
	if tb_name == "" {
		return nil, fmt.Errorf("评论目标表名称不可为空")
	}
	db, err := mysqlGORM.GetMysqlDB()
	if utils.CheckErr(err) {
		return nil, err
	}
	sql := db.Table(fmt.Sprintf("%v as a", new(entitys.Comment).TableName())).
		Joins(fmt.Sprintf("inner join %v as b on a.from_uid=b.id", new(entitys.User).TableName()))
	if req.GetIsReply() != 0 {
		sql = sql.Joins(fmt.Sprintf("inner join %v as c on a.to_uid=c.id", new(entitys.User).TableName()))
	}
	if req.GetUid() != 0 {
		sql = sql.Joins(fmt.Sprintf("left  join (select uid,target_id from %v where uid = %v and type=4) as e on a.id=e.target_id", new(entitys.Like).TableName(), req.GetUid())).
			Select("a.id,a.like_number,a.target_id,a.reply_id,a.from_uid,a.to_uid,a.content,a.created_timestamp,b.head_image as from_head_image,b.nickname as from_nickname,c.head_image as to_head_image,c.nickname as to_nickname,case when e.uid is null then 0 else 1 end as is_like")
	} else {
		sql = sql.Select("a.id,a.like_number,a.target_id,a.reply_id,a.from_uid,a.content,a.created_timestamp,b.head_image as from_head_image,b.nickname as from_nickname,c.head_image as to_head_image,c.nickname as to_nickname")
	}
	sql = sql.Where("a.target_id = ?", target_id).Where("tb_name = ?", tb_name).Where("a.status = ?", 1)

	if req.GetIsReply() != 0 {
		sql = sql.Where("a.is_reply = ?", 1).Where("a.reply_id = ?", req.GetReplyId())
	}
	if req.GetLastId() > 0 {
		sql = sql.Where("a.id < ?", req.GetLastId())
	}
	limit := 20
	if req.GetLimit() > 0 {
		limit = int(req.GetLimit())
	}
	datas := make([]*pb.Comment, 0)
	count := 0
	if err = sql.Count(&count).
		Order("a.id desc").
		Offset(0).
		Limit(limit).Scan(&datas).
		Error; utils.CheckErr(err) {
		return nil, err
	}
	return &pb.CommentList{Count: int64(count), Comments: datas}, nil
}
